Set up

suppressPackageStartupMessages({
  library(tidyverse)
})

Directories and File Inputs/Outputs

# Detect the ".git" folder -- this will be in the project root directory
# Use this as the root directory to ensure proper sourcing of functions 
# no matter where this is called from
root_dir <- rprojroot::find_root(rprojroot::has_dir(".git"))
analysis_dir <- file.path(root_dir, "analyses", "tmb-vaf-longitudinal")
results_dir <- file.path(analysis_dir, "results")
input_dir <- file.path(analysis_dir, "input")
files_dir <- file.path(root_dir, "analyses", "sample-distribution-analysis", "results")

# Input files
genomic_paired_file <- file.path(files_dir, "genomic_assays_matched_time_points_extended.tsv") 
tmb_vaf_file <- file.path(results_dir, "tmb_vaf_genomic.tsv")
palette_file <- file.path(root_dir, "figures", "palettes", "oncoprint_color_palette.tsv")

# File path to plot directory
plots_dir <-
  file.path(analysis_dir, "plots")
if (!dir.exists(plots_dir)) {
  dir.create(plots_dir)
}

source(paste0(root_dir, "/figures/scripts/theme.R"))

Read in data and process

tmb_vaf_df <- readr::read_tsv(tmb_vaf_file, guess_max = 100000, show_col_types = FALSE) %>% 
  filter(!tmb >= 10) %>% 
  select(Kids_First_Biospecimen_ID, Variant_Classification, gene_protein, mutation_count,   region_size, tmb, VAF)

genomic_paired_df <- readr::read_tsv(genomic_paired_file, guess_max = 100000, show_col_types = FALSE) %>% 
  left_join(tmb_vaf_df, by = c("Kids_First_Biospecimen_ID")) %>%
  filter(!is.na(tmb)) 


# Attention as some bs specimen might not have TMB!
# If that happens, we will end up with samples lacking timepoints.

# Which patient samples don't have TMB?
# genomic_paired_df %>% 
#  filter(is.na(tmb)) %>% 
#  unique() %>% 
#  regulartable() %>%
#  fontsize(size = 12, part = "all")

descriptors_df <- genomic_paired_df %>%
  group_by(Kids_First_Participant_ID) %>%
  summarize(descriptors = paste(sort(tumor_descriptor), collapse = ", "),) 


# Vector to order timepoints
timepoints <- c("Diagnosis", "Progressive", "Recurrence", "Deceased", "Second Malignancy", "Unavailable")

df <- genomic_paired_df %>% 
  left_join(descriptors_df, by = c("Kids_First_Participant_ID")) %>% 
  mutate(cgGFAC = case_when(grepl("High-grade glioma", cancer_group) ~ "HGG",
                            grepl("Diffuse midline glioma", cancer_group) ~ "DMG",
                            grepl("Atypical Teratoid Rhabdoid Tumor", cancer_group) ~ "ATRT",
                            grepl("Low-grade glioma", cancer_group) ~ "LGG",
                            TRUE ~ "Other"),
         td_cgGFAC = case_when(grepl("Deceased", tumor_descriptor) ~ "xDeceased",
                                      TRUE ~ tumor_descriptor),
         log10_tmb = abs(log10(tmb)))

# Let's count #samples per cancer groups and timepoints.
# We will use the cg_id col that indicates cancer type as identified at the first diagnostic sample
timepoint_cg_n_df <- df %>% 
  count(cg_id, tumor_descriptor) %>% 
  dplyr::mutate(tumor_descriptor_cg_n = glue::glue("{cg_id}_{tumor_descriptor}  (N={n})")) %>% 
  dplyr::rename(timepoint_cg_n = n) 

# Let's count #samples per cancer groups and timepoints 
timepoint_cgGFAC_n_df <- df %>% 
  count(cgGFAC, td_cgGFAC) %>% 
  dplyr::mutate(tumor_descriptor_cgGFAC_n = glue::glue("{cgGFAC}_{td_cgGFAC}  (N={n})")) %>% 
  dplyr::rename(timepoint_cgGFAC_n = n) 

# Create df to use for plots
df_plot <- df %>% 
  left_join(timepoint_cg_n_df, by = c("tumor_descriptor", "cg_id")) %>%
  left_join(timepoint_cgGFAC_n_df, by = c("td_cgGFAC", "cgGFAC")) %>% 
  filter(!timepoint_cg_n <= 2,
         !timepoint_cgGFAC_n <= 2,
         !cg_id == "NA") %>% 
  mutate(tumor_descriptor = factor(tumor_descriptor),
         tumor_descriptor = fct_relevel(tumor_descriptor, timepoints))
Warning: There was 1 warning in `mutate()`.
ℹ In argument: `tumor_descriptor = fct_relevel(tumor_descriptor, timepoints)`.
Caused by warning:
! 1 unknown level in `f`: Unavailable
# Read color palette
palette_df <- readr::read_tsv(palette_file, guess_max = 100000, show_col_types = FALSE) 

# Define and order palette
palette <- palette_df$hex_codes
names(palette) <- palette_df$Variant_Classification
Warning: Unknown or uninitialised column: `Variant_Classification`.
# Define label for plots
Alteration_type <- df_plot$Variant_Classification

# Define ylim
ylim <- max(df_plot$log10_tmb)

What type of alterations we observe per tumor descriptor?

# Create bxp
print(ggpubr::ggboxplot(df_plot, 
                        x = "tumor_descriptor", 
                        y = "log10_tmb", 
                        color = "Variant_Classification",
                        palette = palette) +
        theme_Publication() + 
        scale_y_continuous(limits = c(0, ylim)) +
        xlab("Timepoint") +
        theme(axis.text.x = element_text(angle = 90)))

# Save the plot
ggsave(filename = "Alteration_type_timepoints.pdf", 
       path = plots_dir, 
       width = 15, 
       height = 8, 
       device = "pdf", 
       useDingbats = FALSE)

What type of alterations we observe per tumor descriptor in each cancer group?

# Create bxp
print(ggpubr::ggboxplot(df_plot, 
                        x = "tumor_descriptor", 
                        y = "log10_tmb", 
                        color = "Variant_Classification",
                        palette = palette) +
        facet_wrap(~cg_id) +
        theme_Publication() + 
        xlab("Timepoint") +
        scale_y_continuous(limits = c(0, ylim)) +
        theme(axis.text.x = element_text(angle = 90)))

# Save the plot
ggsave(filename = "Alteration_type_cancer_group.pdf", 
       path = plots_dir, 
       width = 25, 
       height = 18, 
       device = "pdf", 
       useDingbats = FALSE)

What type of alterations we observe per tumor descriptor in each cancer group defined by cgGFAC?

df_plot_cgGFAC <- df_plot %>% 
  arrange(tumor_descriptor_cgGFAC_n)
  #mutate(tumor_descriptor_cgGFAC_n = factor(tumor_descriptor_cgGFAC_n)) 

#df_plot_cgGFAC$tumor_descriptor_cgGFAC_n %>% levels()

# Create bxp
print(ggpubr::ggboxplot(df_plot_cgGFAC, 
                        x = "tumor_descriptor_cgGFAC_n", 
                        y = "log10_tmb", 
                        color = "Variant_Classification",
                        palette = palette) +
        theme_Publication() + 
        xlab("Timepoint") +
        scale_y_continuous(limits = c(0, ylim)) +
        theme(axis.text.x = element_text(angle = 90)))

# Save the plot
ggsave(filename = "Alteration_type_cgGFAC.pdf", 
       path = plots_dir, 
       width = 14, 
       height = 8, 
       device = "pdf", 
       useDingbats = FALSE)
cgGFAC_id <- as.character(unique(df_plot_cgGFAC$cgGFAC))
cgGFAC_id
[1] "ATRT"  "DMG"   "HGG"   "LGG"   "Other"
ATRT

DMG

HGG

LGG

Other
# Loop through variable
for (i in seq_along(cgGFAC_id)){
  print(i)
  df_sub <- df_plot_cgGFAC %>%
      filter(cgGFAC == cgGFAC_id[i])

  
   # Create bxp
  print(ggpubr::ggboxplot(df_sub, 
                        x = "tumor_descriptor_cgGFAC_n", 
                        y = "log10_tmb", 
                        color = "Variant_Classification",
                        palette = palette) +
        theme_Publication() + 
        labs(title = paste(cgGFAC_id[i])) +
        scale_y_continuous(limits = c(0, ylim)) +
        theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust = 1)))
}
[1] 1

[1] 2

[1] 3

[1] 4

[1] 5

What type of alterations we observe per tumor descriptor in each cancer group (add _n))?

cg <- as.character(unique(df_plot$cg_id))
cg
 [1] "Embryonal tumor with multilayer rosettes"
 [2] "Low-grade glioma"                        
 [3] "Ependymoma"                              
 [4] "Medulloblastoma"                         
 [5] "Atypical Teratoid Rhabdoid Tumor"        
 [6] "Diffuse midline glioma"                  
 [7] "High-grade glioma"                       
 [8] "Ganglioglioma"                           
 [9] "Meningioma"                              
[10] "Pilocytic astrocytoma"                   
[11] "CNS Embryonal tumor"                     
[12] "Neuroblastoma"                           
[13] "Schwannoma"                              
[14] "Chordoma"                                
[15] "Malignant peripheral nerve sheath tumor" 
[16] "Choroid plexus carcinoma"                
[17] "Adamantinomatous Craniopharyngioma"      
[18] "Dysembryoplastic neuroepithelial tumor"  
[19] "Ewing sarcoma"                           
[20] "Rosai-Dorfman disease"                   
[21] "Neurofibroma/Plexiform"                  
[22] "Glial-neuronal tumor"                    
[23] "Hemangioblastoma"                        
[24] "Craniopharyngioma"                       
Embryonal tumor with multilayer rosettes

Low-grade glioma

Ependymoma

Medulloblastoma

Atypical Teratoid Rhabdoid Tumor

Diffuse midline glioma

High-grade glioma

Ganglioglioma

Meningioma

Pilocytic astrocytoma

CNS Embryonal tumor

Neuroblastoma

Schwannoma

Chordoma

Malignant peripheral nerve sheath tumor

Choroid plexus carcinoma

Adamantinomatous Craniopharyngioma

Dysembryoplastic neuroepithelial tumor

Ewing sarcoma

Rosai-Dorfman disease

Neurofibroma/Plexiform

Glial-neuronal tumor

Hemangioblastoma

Craniopharyngioma
# Loop through variable
for (i in seq_along(cg)){
  print(i)
  df_sub <- df_plot %>%
      filter(cg_id == cg[i])
  
  # Create bxp
  print(ggpubr::ggboxplot(df_sub, 
                        x = "tumor_descriptor_cg_n", 
                        y = "log10_tmb", 
                        color = "Variant_Classification",
                        palette = palette) +
        theme_Publication() + 
        xlab("Timepoint") +
        labs(title = paste(cg[i])) +
        scale_y_continuous(limits = c(0, ylim)) +
        theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust = 1)))
}
[1] 1

[1] 2

[1] 3

[1] 4

[1] 5

[1] 6

[1] 7

[1] 8

[1] 9

[1] 10

[1] 11

[1] 12

[1] 13

[1] 14

[1] 15

[1] 16

[1] 17

[1] 18

[1] 19

[1] 20

[1] 21

[1] 22

[1] 23

[1] 24

What type of alterations we observe per tumor descriptor in each cancer group and timepoint model?

tm <- as.character(unique(df_plot$timepoints_models))
tm
 [1] "Dx-Rec"         "Dx-Pro"         "Dx-Dec"         "Pro-Dec"       
 [5] "Rec-SM"         "Pro-Rec"        "Dx-SM"          "Pro-Rec-Dec"   
 [9] "Dx-Pro-Rec"     "Rec-Dec"        "Dx-Pro-Rec-Dec" "Dx-Rec-Dec"    
[13] "Dx-Pro-Dec"    
Dx-Rec

Dx-Pro

Dx-Dec

Pro-Dec

Rec-SM

Pro-Rec

Dx-SM

Pro-Rec-Dec

Dx-Pro-Rec

Rec-Dec

Dx-Pro-Rec-Dec

Dx-Rec-Dec

Dx-Pro-Dec
# Loop through variable
for (i in seq_along(tm)){
  print(i)
  df_sub <- df_plot %>%
      filter(timepoints_models == tm[i])
  
  # Create bxp
  print(ggpubr::ggboxplot(df_sub, 
                        x = "tumor_descriptor", 
                        y = "tmb", 
                        color = "Variant_Classification",
                        palette = palette) +
        facet_wrap(~cancer_group) +
        theme_Publication() +
        ylab("TMB") +
        xlab("Timepoint") +
        scale_y_continuous(limits = c(0, ylim)) +
        theme(axis.text.x = element_text(angle = 90)))
}
[1] 1
Warning: Removed 224 rows containing non-finite values (`stat_boxplot()`).

[1] 2
Warning: Removed 1153 rows containing non-finite values (`stat_boxplot()`).

[1] 3
Warning: Removed 370 rows containing non-finite values (`stat_boxplot()`).

[1] 4
Warning: Removed 169 rows containing non-finite values (`stat_boxplot()`).

[1] 5
Warning: Removed 93 rows containing non-finite values (`stat_boxplot()`).

[1] 6
Warning: Removed 127 rows containing non-finite values (`stat_boxplot()`).

[1] 7

[1] 8
Warning: Removed 510 rows containing non-finite values (`stat_boxplot()`).

[1] 9
Warning: Removed 158 rows containing non-finite values (`stat_boxplot()`).

[1] 10

[1] 11
Warning: Removed 175 rows containing non-finite values (`stat_boxplot()`).

[1] 12

[1] 13
Warning: Removed 62 rows containing non-finite values (`stat_boxplot()`).

sessionInfo()
R version 4.2.3 (2023-03-15)
Platform: aarch64-apple-darwin20 (64-bit)
Running under: macOS Ventura 13.5.1

Matrix products: default
BLAS:   /Library/Frameworks/R.framework/Versions/4.2-arm64/Resources/lib/libRblas.0.dylib
LAPACK: /Library/Frameworks/R.framework/Versions/4.2-arm64/Resources/lib/libRlapack.dylib

locale:
[1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8

attached base packages:
[1] grid      stats     graphics  grDevices utils     datasets  methods  
[8] base     

other attached packages:
 [1] ggthemes_4.2.4  lubridate_1.9.2 forcats_1.0.0   stringr_1.5.0  
 [5] dplyr_1.1.2     purrr_1.0.1     readr_2.1.4     tidyr_1.3.0    
 [9] tibble_3.2.1    ggplot2_3.4.2   tidyverse_2.0.0

loaded via a namespace (and not attached):
 [1] tidyselect_1.2.0  xfun_0.39         bslib_0.5.0       carData_3.0-5    
 [5] colorspace_2.1-0  vctrs_0.6.3       generics_0.1.3    htmltools_0.5.5  
 [9] yaml_2.3.7        utf8_1.2.3        rlang_1.1.1       jquerylib_0.1.4  
[13] pillar_1.9.0      ggpubr_0.6.0      glue_1.6.2        withr_2.5.0      
[17] bit64_4.0.5       lifecycle_1.0.3   munsell_0.5.0     ggsignif_0.6.4   
[21] gtable_0.3.3      ragg_1.2.5        evaluate_0.21     labeling_0.4.2   
[25] knitr_1.43        tzdb_0.4.0        fastmap_1.1.1     parallel_4.2.3   
[29] fansi_1.0.4       highr_0.10        broom_1.0.5       scales_1.2.1     
[33] backports_1.4.1   cachem_1.0.8      vroom_1.6.3       jsonlite_1.8.7   
[37] abind_1.4-5       systemfonts_1.0.4 farver_2.1.1      bit_4.0.5        
[41] textshaping_0.3.6 hms_1.1.3         digest_0.6.33     stringi_1.7.12   
[45] rstatix_0.7.2     rprojroot_2.0.3   cli_3.6.1         tools_4.2.3      
[49] magrittr_2.0.3    sass_0.4.7        crayon_1.5.2      car_3.1-2        
[53] pkgconfig_2.0.3   timechange_0.2.0  rmarkdown_2.23    R6_2.5.1         
[57] compiler_4.2.3   
LS0tCnRpdGxlOiAiQ2xhc3NpZmljYXRpb24gb2YgVmFyaWFudHMgYWNyb3NzIHBhaXJlZCBsb25naXR1ZGluYWwgc2FtcGxlcyBpbiB0aGUgUEJUQSBDb2hvcnQiCmF1dGhvcjogJ0FudG9uaWEgQ2hyb25pIDxjaHJvbmlhQGNob3AuZWR1PiBhbmQgSm8gTHlubmUgUm9raXRhIDxyb2tpdGFAY2hvcC5lZHU+IGZvciBEM0InCmRhdGU6ICIyMDIzIgpvdXRwdXQ6CiAgaHRtbF9ub3RlYm9vazoKICAgIHRvYzogVFJVRQogICAgdG9jX2Zsb2F0OiBUUlVFCi0tLQoKIyBTZXQgdXAKYGBge3IgbG9hZC1saWJyYXJ5fQpzdXBwcmVzc1BhY2thZ2VTdGFydHVwTWVzc2FnZXMoewogIGxpYnJhcnkodGlkeXZlcnNlKQp9KQpgYGAKCiMjIERpcmVjdG9yaWVzIGFuZCBGaWxlIElucHV0cy9PdXRwdXRzCmBgYHtyIHNldC1kaXItYW5kLWZpbGUtbmFtZXN9CiMgRGV0ZWN0IHRoZSAiLmdpdCIgZm9sZGVyIC0tIHRoaXMgd2lsbCBiZSBpbiB0aGUgcHJvamVjdCByb290IGRpcmVjdG9yeQojIFVzZSB0aGlzIGFzIHRoZSByb290IGRpcmVjdG9yeSB0byBlbnN1cmUgcHJvcGVyIHNvdXJjaW5nIG9mIGZ1bmN0aW9ucyAKIyBubyBtYXR0ZXIgd2hlcmUgdGhpcyBpcyBjYWxsZWQgZnJvbQpyb290X2RpciA8LSBycHJvanJvb3Q6OmZpbmRfcm9vdChycHJvanJvb3Q6Omhhc19kaXIoIi5naXQiKSkKYW5hbHlzaXNfZGlyIDwtIGZpbGUucGF0aChyb290X2RpciwgImFuYWx5c2VzIiwgInRtYi12YWYtbG9uZ2l0dWRpbmFsIikKcmVzdWx0c19kaXIgPC0gZmlsZS5wYXRoKGFuYWx5c2lzX2RpciwgInJlc3VsdHMiKQppbnB1dF9kaXIgPC0gZmlsZS5wYXRoKGFuYWx5c2lzX2RpciwgImlucHV0IikKZmlsZXNfZGlyIDwtIGZpbGUucGF0aChyb290X2RpciwgImFuYWx5c2VzIiwgInNhbXBsZS1kaXN0cmlidXRpb24tYW5hbHlzaXMiLCAicmVzdWx0cyIpCgojIElucHV0IGZpbGVzCmdlbm9taWNfcGFpcmVkX2ZpbGUgPC0gZmlsZS5wYXRoKGZpbGVzX2RpciwgImdlbm9taWNfYXNzYXlzX21hdGNoZWRfdGltZV9wb2ludHNfZXh0ZW5kZWQudHN2IikgCnRtYl92YWZfZmlsZSA8LSBmaWxlLnBhdGgocmVzdWx0c19kaXIsICJ0bWJfdmFmX2dlbm9taWMudHN2IikKcGFsZXR0ZV9maWxlIDwtIGZpbGUucGF0aChyb290X2RpciwgImZpZ3VyZXMiLCAicGFsZXR0ZXMiLCAib25jb3ByaW50X2NvbG9yX3BhbGV0dGUudHN2IikKCiMgRmlsZSBwYXRoIHRvIHBsb3QgZGlyZWN0b3J5CnBsb3RzX2RpciA8LQogIGZpbGUucGF0aChhbmFseXNpc19kaXIsICJwbG90cyIpCmlmICghZGlyLmV4aXN0cyhwbG90c19kaXIpKSB7CiAgZGlyLmNyZWF0ZShwbG90c19kaXIpCn0KCnNvdXJjZShwYXN0ZTAocm9vdF9kaXIsICIvZmlndXJlcy9zY3JpcHRzL3RoZW1lLlIiKSkKYGBgCgojIyBSZWFkIGluIGRhdGEgYW5kIHByb2Nlc3MKYGBge3IgbG9hZC1wcm9jZXNzLWlucHV0c30KdG1iX3ZhZl9kZiA8LSByZWFkcjo6cmVhZF90c3YodG1iX3ZhZl9maWxlLCBndWVzc19tYXggPSAxMDAwMDAsIHNob3dfY29sX3R5cGVzID0gRkFMU0UpICU+JSAKICBmaWx0ZXIoIXRtYiA+PSAxMCkgJT4lIAogIHNlbGVjdChLaWRzX0ZpcnN0X0Jpb3NwZWNpbWVuX0lELCBWYXJpYW50X0NsYXNzaWZpY2F0aW9uLCBnZW5lX3Byb3RlaW4sIG11dGF0aW9uX2NvdW50LAlyZWdpb25fc2l6ZSwgdG1iLCBWQUYpCgpnZW5vbWljX3BhaXJlZF9kZiA8LSByZWFkcjo6cmVhZF90c3YoZ2Vub21pY19wYWlyZWRfZmlsZSwgZ3Vlc3NfbWF4ID0gMTAwMDAwLCBzaG93X2NvbF90eXBlcyA9IEZBTFNFKSAlPiUgCiAgbGVmdF9qb2luKHRtYl92YWZfZGYsIGJ5ID0gYygiS2lkc19GaXJzdF9CaW9zcGVjaW1lbl9JRCIpKSAlPiUKICBmaWx0ZXIoIWlzLm5hKHRtYikpIAoKCiMgQXR0ZW50aW9uIGFzIHNvbWUgYnMgc3BlY2ltZW4gbWlnaHQgbm90IGhhdmUgVE1CIQojIElmIHRoYXQgaGFwcGVucywgd2Ugd2lsbCBlbmQgdXAgd2l0aCBzYW1wbGVzIGxhY2tpbmcgdGltZXBvaW50cy4KCiMgV2hpY2ggcGF0aWVudCBzYW1wbGVzIGRvbid0IGhhdmUgVE1CPwojIGdlbm9taWNfcGFpcmVkX2RmICU+JSAKIyAgZmlsdGVyKGlzLm5hKHRtYikpICU+JSAKIyAgdW5pcXVlKCkgJT4lIAojICByZWd1bGFydGFibGUoKSAlPiUKIyAgZm9udHNpemUoc2l6ZSA9IDEyLCBwYXJ0ID0gImFsbCIpCgpkZXNjcmlwdG9yc19kZiA8LSBnZW5vbWljX3BhaXJlZF9kZiAlPiUKICBncm91cF9ieShLaWRzX0ZpcnN0X1BhcnRpY2lwYW50X0lEKSAlPiUKICBzdW1tYXJpemUoZGVzY3JpcHRvcnMgPSBwYXN0ZShzb3J0KHR1bW9yX2Rlc2NyaXB0b3IpLCBjb2xsYXBzZSA9ICIsICIpLCkgCgoKIyBWZWN0b3IgdG8gb3JkZXIgdGltZXBvaW50cwp0aW1lcG9pbnRzIDwtIGMoIkRpYWdub3NpcyIsICJQcm9ncmVzc2l2ZSIsICJSZWN1cnJlbmNlIiwgIkRlY2Vhc2VkIiwgIlNlY29uZCBNYWxpZ25hbmN5IiwgIlVuYXZhaWxhYmxlIikKCmRmIDwtIGdlbm9taWNfcGFpcmVkX2RmICU+JSAKICBsZWZ0X2pvaW4oZGVzY3JpcHRvcnNfZGYsIGJ5ID0gYygiS2lkc19GaXJzdF9QYXJ0aWNpcGFudF9JRCIpKSAlPiUgCiAgbXV0YXRlKGNnR0ZBQyA9IGNhc2Vfd2hlbihncmVwbCgiSGlnaC1ncmFkZSBnbGlvbWEiLCBjYW5jZXJfZ3JvdXApIH4gIkhHRyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBncmVwbCgiRGlmZnVzZSBtaWRsaW5lIGdsaW9tYSIsIGNhbmNlcl9ncm91cCkgfiAiRE1HIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdyZXBsKCJBdHlwaWNhbCBUZXJhdG9pZCBSaGFiZG9pZCBUdW1vciIsIGNhbmNlcl9ncm91cCkgfiAiQVRSVCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICBncmVwbCgiTG93LWdyYWRlIGdsaW9tYSIsIGNhbmNlcl9ncm91cCkgfiAiTEdHIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUUgfiAiT3RoZXIiKSwKICAgICAgICAgdGRfY2dHRkFDID0gY2FzZV93aGVuKGdyZXBsKCJEZWNlYXNlZCIsIHR1bW9yX2Rlc2NyaXB0b3IpIH4gInhEZWNlYXNlZCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVFJVRSB+IHR1bW9yX2Rlc2NyaXB0b3IpLAogICAgICAgICBsb2cxMF90bWIgPSBhYnMobG9nMTAodG1iKSkpCgojIExldCdzIGNvdW50ICNzYW1wbGVzIHBlciBjYW5jZXIgZ3JvdXBzIGFuZCB0aW1lcG9pbnRzLgojIFdlIHdpbGwgdXNlIHRoZSBjZ19pZCBjb2wgdGhhdCBpbmRpY2F0ZXMgY2FuY2VyIHR5cGUgYXMgaWRlbnRpZmllZCBhdCB0aGUgZmlyc3QgZGlhZ25vc3RpYyBzYW1wbGUKdGltZXBvaW50X2NnX25fZGYgPC0gZGYgJT4lIAogIGNvdW50KGNnX2lkLCB0dW1vcl9kZXNjcmlwdG9yKSAlPiUgCiAgZHBseXI6Om11dGF0ZSh0dW1vcl9kZXNjcmlwdG9yX2NnX24gPSBnbHVlOjpnbHVlKCJ7Y2dfaWR9X3t0dW1vcl9kZXNjcmlwdG9yfSAgKE49e259KSIpKSAlPiUgCiAgZHBseXI6OnJlbmFtZSh0aW1lcG9pbnRfY2dfbiA9IG4pIAoKIyBMZXQncyBjb3VudCAjc2FtcGxlcyBwZXIgY2FuY2VyIGdyb3VwcyBhbmQgdGltZXBvaW50cyAKdGltZXBvaW50X2NnR0ZBQ19uX2RmIDwtIGRmICU+JSAKICBjb3VudChjZ0dGQUMsIHRkX2NnR0ZBQykgJT4lIAogIGRwbHlyOjptdXRhdGUodHVtb3JfZGVzY3JpcHRvcl9jZ0dGQUNfbiA9IGdsdWU6OmdsdWUoIntjZ0dGQUN9X3t0ZF9jZ0dGQUN9ICAoTj17bn0pIikpICU+JSAKICBkcGx5cjo6cmVuYW1lKHRpbWVwb2ludF9jZ0dGQUNfbiA9IG4pIAoKIyBDcmVhdGUgZGYgdG8gdXNlIGZvciBwbG90cwpkZl9wbG90IDwtIGRmICU+JSAKICBsZWZ0X2pvaW4odGltZXBvaW50X2NnX25fZGYsIGJ5ID0gYygidHVtb3JfZGVzY3JpcHRvciIsICJjZ19pZCIpKSAlPiUKICBsZWZ0X2pvaW4odGltZXBvaW50X2NnR0ZBQ19uX2RmLCBieSA9IGMoInRkX2NnR0ZBQyIsICJjZ0dGQUMiKSkgJT4lIAogIGZpbHRlcighdGltZXBvaW50X2NnX24gPD0gMiwKICAgICAgICAgIXRpbWVwb2ludF9jZ0dGQUNfbiA8PSAyLAogICAgICAgICAhY2dfaWQgPT0gIk5BIikgJT4lIAogIG11dGF0ZSh0dW1vcl9kZXNjcmlwdG9yID0gZmFjdG9yKHR1bW9yX2Rlc2NyaXB0b3IpLAogICAgICAgICB0dW1vcl9kZXNjcmlwdG9yID0gZmN0X3JlbGV2ZWwodHVtb3JfZGVzY3JpcHRvciwgdGltZXBvaW50cykpCiAgICAgICAgCmBgYCAKCgpgYGB7ciBkZWZpbmUtcGFyYW1ldGVycy1mb3ItcGxvdHN9CiMgUmVhZCBjb2xvciBwYWxldHRlCnBhbGV0dGVfZGYgPC0gcmVhZHI6OnJlYWRfdHN2KHBhbGV0dGVfZmlsZSwgZ3Vlc3NfbWF4ID0gMTAwMDAwLCBzaG93X2NvbF90eXBlcyA9IEZBTFNFKSAKCiMgRGVmaW5lIGFuZCBvcmRlciBwYWxldHRlCnBhbGV0dGUgPC0gcGFsZXR0ZV9kZiRoZXhfY29kZXMKbmFtZXMocGFsZXR0ZSkgPC0gcGFsZXR0ZV9kZiRWYXJpYW50X0NsYXNzaWZpY2F0aW9uCgojIERlZmluZSBsYWJlbCBmb3IgcGxvdHMKQWx0ZXJhdGlvbl90eXBlIDwtIGRmX3Bsb3QkVmFyaWFudF9DbGFzc2lmaWNhdGlvbgoKIyBEZWZpbmUgeWxpbQp5bGltIDwtIG1heChkZl9wbG90JGxvZzEwX3RtYikKYGBgCgojIFdoYXQgdHlwZSBvZiBhbHRlcmF0aW9ucyB3ZSBvYnNlcnZlIHBlciB0dW1vciBkZXNjcmlwdG9yPwoKYGBge3IgcGxvdC10aW1lcG9pbnQsIGZpZy53aWR0aCA9IDE1LCBmaWcuaGVpZ2h0ID0gOCwgZmlnLmZ1bGx3aWR0aCA9IFRSVUV9CiMgQ3JlYXRlIGJ4cApwcmludChnZ3B1YnI6OmdnYm94cGxvdChkZl9wbG90LCAKICAgICAgICAgICAgICAgICAgICAgICAgeCA9ICJ0dW1vcl9kZXNjcmlwdG9yIiwgCiAgICAgICAgICAgICAgICAgICAgICAgIHkgPSAibG9nMTBfdG1iIiwgCiAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9yID0gIlZhcmlhbnRfQ2xhc3NpZmljYXRpb24iLAogICAgICAgICAgICAgICAgICAgICAgICBwYWxldHRlID0gcGFsZXR0ZSkgKwogICAgICAgIHRoZW1lX1B1YmxpY2F0aW9uKCkgKyAKICAgICAgICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygwLCB5bGltKSkgKwogICAgICAgIHhsYWIoIlRpbWVwb2ludCIpICsKICAgICAgICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwKSkpCgojIFNhdmUgdGhlIHBsb3QKZ2dzYXZlKGZpbGVuYW1lID0gIkFsdGVyYXRpb25fdHlwZV90aW1lcG9pbnRzLnBkZiIsIAogICAgICAgcGF0aCA9IHBsb3RzX2RpciwgCiAgICAgICB3aWR0aCA9IDE1LCAKICAgICAgIGhlaWdodCA9IDgsIAogICAgICAgZGV2aWNlID0gInBkZiIsIAogICAgICAgdXNlRGluZ2JhdHMgPSBGQUxTRSkKYGBgCgoKIyBXaGF0IHR5cGUgb2YgYWx0ZXJhdGlvbnMgd2Ugb2JzZXJ2ZSBwZXIgdHVtb3IgZGVzY3JpcHRvciBpbiBlYWNoIGNhbmNlciBncm91cD8KCmBgYHtyIHBsb3QtY2ctaWQsIGZpZy53aWR0aCA9IDI1LCBmaWcuaGVpZ2h0ID0gMTgsIGZpZy5mdWxsd2lkdGggPSBUUlVFfQojIENyZWF0ZSBieHAKcHJpbnQoZ2dwdWJyOjpnZ2JveHBsb3QoZGZfcGxvdCwgCiAgICAgICAgICAgICAgICAgICAgICAgIHggPSAidHVtb3JfZGVzY3JpcHRvciIsIAogICAgICAgICAgICAgICAgICAgICAgICB5ID0gImxvZzEwX3RtYiIsIAogICAgICAgICAgICAgICAgICAgICAgICBjb2xvciA9ICJWYXJpYW50X0NsYXNzaWZpY2F0aW9uIiwKICAgICAgICAgICAgICAgICAgICAgICAgcGFsZXR0ZSA9IHBhbGV0dGUpICsKICAgICAgICBmYWNldF93cmFwKH5jZ19pZCkgKwogICAgICAgIHRoZW1lX1B1YmxpY2F0aW9uKCkgKyAKICAgICAgICB4bGFiKCJUaW1lcG9pbnQiKSArCiAgICAgICAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwgeWxpbSkpICsKICAgICAgICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwKSkpCgojIFNhdmUgdGhlIHBsb3QKZ2dzYXZlKGZpbGVuYW1lID0gIkFsdGVyYXRpb25fdHlwZV9jYW5jZXJfZ3JvdXAucGRmIiwgCiAgICAgICBwYXRoID0gcGxvdHNfZGlyLCAKICAgICAgIHdpZHRoID0gMjUsIAogICAgICAgaGVpZ2h0ID0gMTgsIAogICAgICAgZGV2aWNlID0gInBkZiIsIAogICAgICAgdXNlRGluZ2JhdHMgPSBGQUxTRSkKYGBgCgoKIyBXaGF0IHR5cGUgb2YgYWx0ZXJhdGlvbnMgd2Ugb2JzZXJ2ZSBwZXIgdHVtb3IgZGVzY3JpcHRvciBpbiBlYWNoIGNhbmNlciBncm91cCBkZWZpbmVkIGJ5IGNnR0ZBQz8KCmBgYHtyIHBsb3QtY2dHRkFDLW4sIGZpZy53aWR0aCA9IDE0LCBmaWcuaGVpZ2h0ID0gOCwgZmlnLmZ1bGx3aWR0aCA9IFRSVUV9CmRmX3Bsb3RfY2dHRkFDIDwtIGRmX3Bsb3QgJT4lIAogIGFycmFuZ2UodHVtb3JfZGVzY3JpcHRvcl9jZ0dGQUNfbikKICAjbXV0YXRlKHR1bW9yX2Rlc2NyaXB0b3JfY2dHRkFDX24gPSBmYWN0b3IodHVtb3JfZGVzY3JpcHRvcl9jZ0dGQUNfbikpIAoKI2RmX3Bsb3RfY2dHRkFDJHR1bW9yX2Rlc2NyaXB0b3JfY2dHRkFDX24gJT4lIGxldmVscygpCgojIENyZWF0ZSBieHAKcHJpbnQoZ2dwdWJyOjpnZ2JveHBsb3QoZGZfcGxvdF9jZ0dGQUMsIAogICAgICAgICAgICAgICAgICAgICAgICB4ID0gInR1bW9yX2Rlc2NyaXB0b3JfY2dHRkFDX24iLCAKICAgICAgICAgICAgICAgICAgICAgICAgeSA9ICJsb2cxMF90bWIiLCAKICAgICAgICAgICAgICAgICAgICAgICAgY29sb3IgPSAiVmFyaWFudF9DbGFzc2lmaWNhdGlvbiIsCiAgICAgICAgICAgICAgICAgICAgICAgIHBhbGV0dGUgPSBwYWxldHRlKSArCiAgICAgICAgdGhlbWVfUHVibGljYXRpb24oKSArIAogICAgICAgIHhsYWIoIlRpbWVwb2ludCIpICsKICAgICAgICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygwLCB5bGltKSkgKwogICAgICAgIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTApKSkKCiMgU2F2ZSB0aGUgcGxvdApnZ3NhdmUoZmlsZW5hbWUgPSAiQWx0ZXJhdGlvbl90eXBlX2NnR0ZBQy5wZGYiLCAKICAgICAgIHBhdGggPSBwbG90c19kaXIsIAogICAgICAgd2lkdGggPSAxNCwgCiAgICAgICBoZWlnaHQgPSA4LCAKICAgICAgIGRldmljZSA9ICJwZGYiLCAKICAgICAgIHVzZURpbmdiYXRzID0gRkFMU0UpCgpgYGAKCgpgYGB7ciBwbG90LWNnR0ZBQy1uLWluZGl2aWR1YWwtcGxvdHMsIGZpZy53aWR0aCA9IDgsIGZpZy5oZWlnaHQgPSA2LCBmaWcuZnVsbHdpZHRoID0gVFJVRX0KY2dHRkFDX2lkIDwtIGFzLmNoYXJhY3Rlcih1bmlxdWUoZGZfcGxvdF9jZ0dGQUMkY2dHRkFDKSkKY2dHRkFDX2lkCgojIExvb3AgdGhyb3VnaCB2YXJpYWJsZQpmb3IgKGkgaW4gc2VxX2Fsb25nKGNnR0ZBQ19pZCkpewogIHByaW50KGkpCiAgZGZfc3ViIDwtIGRmX3Bsb3RfY2dHRkFDICU+JQogICAgICBmaWx0ZXIoY2dHRkFDID09IGNnR0ZBQ19pZFtpXSkKCiAgCiAgICMgQ3JlYXRlIGJ4cAogIHByaW50KGdncHVicjo6Z2dib3hwbG90KGRmX3N1YiwgCiAgICAgICAgICAgICAgICAgICAgICAgIHggPSAidHVtb3JfZGVzY3JpcHRvcl9jZ0dGQUNfbiIsIAogICAgICAgICAgICAgICAgICAgICAgICB5ID0gImxvZzEwX3RtYiIsIAogICAgICAgICAgICAgICAgICAgICAgICBjb2xvciA9ICJWYXJpYW50X0NsYXNzaWZpY2F0aW9uIiwKICAgICAgICAgICAgICAgICAgICAgICAgcGFsZXR0ZSA9IHBhbGV0dGUpICsKICAgICAgICB0aGVtZV9QdWJsaWNhdGlvbigpICsgCiAgICAgICAgbGFicyh0aXRsZSA9IHBhc3RlKGNnR0ZBQ19pZFtpXSkpICsKICAgICAgICBzY2FsZV95X2NvbnRpbnVvdXMobGltaXRzID0gYygwLCB5bGltKSkgKwogICAgICAgIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTAsIHZqdXN0ID0gMC41LCBoanVzdCA9IDEpKSkKfQpgYGAKCiMgV2hhdCB0eXBlIG9mIGFsdGVyYXRpb25zIHdlIG9ic2VydmUgcGVyIHR1bW9yIGRlc2NyaXB0b3IgaW4gZWFjaCBjYW5jZXIgZ3JvdXAgKGFkZCBfbikpPwogCgpgYGB7ciBwbG90LW4sIGZpZy53aWR0aCA9IDEyLCBmaWcuaGVpZ2h0ID0gOCwgZmlnLmZ1bGx3aWR0aCA9IFRSVUV9CmNnIDwtIGFzLmNoYXJhY3Rlcih1bmlxdWUoZGZfcGxvdCRjZ19pZCkpCmNnCgojIExvb3AgdGhyb3VnaCB2YXJpYWJsZQpmb3IgKGkgaW4gc2VxX2Fsb25nKGNnKSl7CiAgcHJpbnQoaSkKICBkZl9zdWIgPC0gZGZfcGxvdCAlPiUKICAgICAgZmlsdGVyKGNnX2lkID09IGNnW2ldKQogIAogICMgQ3JlYXRlIGJ4cAogIHByaW50KGdncHVicjo6Z2dib3hwbG90KGRmX3N1YiwgCiAgICAgICAgICAgICAgICAgICAgICAgIHggPSAidHVtb3JfZGVzY3JpcHRvcl9jZ19uIiwgCiAgICAgICAgICAgICAgICAgICAgICAgIHkgPSAibG9nMTBfdG1iIiwgCiAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9yID0gIlZhcmlhbnRfQ2xhc3NpZmljYXRpb24iLAogICAgICAgICAgICAgICAgICAgICAgICBwYWxldHRlID0gcGFsZXR0ZSkgKwogICAgICAgIHRoZW1lX1B1YmxpY2F0aW9uKCkgKyAKICAgICAgICB4bGFiKCJUaW1lcG9pbnQiKSArCiAgICAgICAgbGFicyh0aXRsZSA9IHBhc3RlKGNnW2ldKSkgKwogICAgICAgIHNjYWxlX3lfY29udGludW91cyhsaW1pdHMgPSBjKDAsIHlsaW0pKSArCiAgICAgICAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCwgdmp1c3QgPSAwLjUsIGhqdXN0ID0gMSkpKQp9CmBgYAoKCiMgV2hhdCB0eXBlIG9mIGFsdGVyYXRpb25zIHdlIG9ic2VydmUgcGVyIHR1bW9yIGRlc2NyaXB0b3IgaW4gZWFjaCBjYW5jZXIgZ3JvdXAgYW5kIHRpbWVwb2ludCBtb2RlbD8KCmBgYHtyIHBsb3QtdGltZXBvaW50LW1vZGVsLCBmaWcud2lkdGggPSAyNSwgZmlnLmhlaWdodCA9IDE4LCBmaWcuZnVsbHdpZHRoID0gVFJVRX0KdG0gPC0gYXMuY2hhcmFjdGVyKHVuaXF1ZShkZl9wbG90JHRpbWVwb2ludHNfbW9kZWxzKSkKdG0KCiMgTG9vcCB0aHJvdWdoIHZhcmlhYmxlCmZvciAoaSBpbiBzZXFfYWxvbmcodG0pKXsKICBwcmludChpKQogIGRmX3N1YiA8LSBkZl9wbG90ICU+JQogICAgICBmaWx0ZXIodGltZXBvaW50c19tb2RlbHMgPT0gdG1baV0pCiAgCiAgIyBDcmVhdGUgYnhwCiAgcHJpbnQoZ2dwdWJyOjpnZ2JveHBsb3QoZGZfc3ViLCAKICAgICAgICAgICAgICAgICAgICAgICAgeCA9ICJ0dW1vcl9kZXNjcmlwdG9yIiwgCiAgICAgICAgICAgICAgICAgICAgICAgIHkgPSAidG1iIiwgCiAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9yID0gIlZhcmlhbnRfQ2xhc3NpZmljYXRpb24iLAogICAgICAgICAgICAgICAgICAgICAgICBwYWxldHRlID0gcGFsZXR0ZSkgKwogICAgICAgIGZhY2V0X3dyYXAofmNhbmNlcl9ncm91cCkgKwogICAgICAgIHRoZW1lX1B1YmxpY2F0aW9uKCkgKwogICAgICAgIHlsYWIoIlRNQiIpICsKICAgICAgICB4bGFiKCJUaW1lcG9pbnQiKSArCiAgICAgICAgc2NhbGVfeV9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwgeWxpbSkpICsKICAgICAgICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwKSkpCn0KYGBgCgoKYGBge3IgZWNobz1UUlVFfQpzZXNzaW9uSW5mbygpCmBgYAo=